package woordvoorspeller.core;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * A WordsList is a list of words. This list is read from a plain text file. Each word is separated by a new line. 
 * TODO: Capital and space support, Set instead of List?, URI instead of String.
 * @author Brian Setz
 * @version 0.1
 */
public class WordList 
{
	// Main list of words.
	private ArrayList<WordListEntry> list; 
	private String path;
	/**
	 * Creates a WordsList.
	 * @param path The location of the plain text file with words.
	 * @throws WordListFormatException If the plain text file for the WordList is in a invalid format an exception will the thrown.
	 */
	public WordList(String path) throws WordListFormatException
	{
		this.path = path;
		list = new ArrayList<WordListEntry>();
		// Parse the file.
		this.importWordFile();
	}

	/**
	 * Parses the plain text file from the path given at the constructor and puts the words in an ArrayList.
	 * @throws WordListFormatException If the plain text file for the WordList is in a invalid format an exception will the thrown. 
	 */
	public void importWordFile() throws WordListFormatException
	{
		importWordFile(path);
	}
	
	/**
	 * Parses the plain text file and puts the words in an ArrayList.
	 * @param path The location of the plain text file with words.
	 * @throws WordListFormatException If the plain text file for the WordList is in a invalid format an exception will the thrown. 
	 */
	private void importWordFile(String path) throws WordListFormatException
	{
		// Double check if the list is empty.
		if(list.isEmpty() == false)
			return;
		
		// Simple file IO.
		try 
		{
			// Open a BufferedReader input.
			BufferedReader in = new BufferedReader(new FileReader(path));
		
			// Parse the file line by line.
			String line = null;
			while((line = in.readLine()) != null)
			{
				// Split the line.
				String[] lineArray = line.split(",");
				
				// Check if the lineArray is valid.
				if(!this.isValidArray(lineArray))
					throw new WordListFormatException();
					
				// Add each word and priority to the ArrayList as a new WordListEntry.
				list.add(new WordListEntry(lineArray[0], Integer.parseInt(lineArray[1])));
			}
			
			// Close the reader.
			in.close();
		}
		catch(FileNotFoundException e)
		{
			System.out.println(e.getMessage());
			e.printStackTrace();
		}
		catch(IOException e)
		{
			System.out.println(e.getMessage());
			e.printStackTrace();
		}
	}
	
	/**
	 * Saves the wordList array as a plain text file to the path given at the constructor. 
	 */
	public void exportWordFile()
	{
		exportWordFile(path);
	}
	
	/**
	 * Saves the wordList array as a plain text file. 
	 * @param path The location where the plain text file should be written.
	 */
	public void exportWordFile(String path)
	{	
		// Double check if the list is full.
		if(list.isEmpty() == true)
			return;		
		
		// Simple file IO.
		try
		{
			// Open a BufferedWriter output.
			BufferedWriter out = new BufferedWriter(new FileWriter(path));
			
			// Loop all the entries in the list and write each one to the file.
			for(WordListEntry entry: list)
			{
				out.write(entry.getWord()+","+entry.getPriority());
				out.write("\n");
				out.flush();
			}
			
			// Close the writer.
			out.close();
		}
		catch(FileNotFoundException e)
		{
			System.out.println(e.getMessage());
			e.printStackTrace();
		}		
		catch(IOException e)
		{
			System.out.println(e.getMessage());
			e.printStackTrace();			
		}
	}
	/**
	 * Searches for the specified word and returns an ArrayList with matches.
	 * @param word The word to search for.
	 * @return The ArrayList with matches.
	 */
	public ArrayList<WordListEntry> getWords(String word)
	{
		// Sub list with the results.
		ArrayList<WordListEntry> wordList = new ArrayList<WordListEntry>();
		
		// Iterate trough the main list.	
		Iterator<WordListEntry> iter = list.iterator();
		while(iter.hasNext())
		{
			WordListEntry nextEntry = iter.next();
			String nextWord = nextEntry.getWord();
			if(nextWord.startsWith(word))
			{
				// If a match is found, add it to the sub list.
				wordList.add(nextEntry);
			}
		}
		
		// Sort the list (natural sorting).
		Collections.sort(wordList);
		
		return wordList;
	}
	
	/**
	 * 
	 * @param word
	 */
	public void increasePriority(String word)
	{
		Iterator<WordListEntry> iter = list.iterator();
		while(iter.hasNext())
		{
			WordListEntry nextEntry = iter.next();
			String nextWord = nextEntry.getWord();
			if(nextWord.equals(word))
			{
				nextEntry.setPriority(nextEntry.getPriority()+1);
			}
		}		
	}
	
	/**
	 * 
	 * @param word
	 * @return
	 */
	public boolean containsWord(String word)
	{
		Iterator<WordListEntry> iter = list.iterator();
		while(iter.hasNext())
		{
			WordListEntry nextEntry = iter.next();
			String nextWord = nextEntry.getWord();
			if(nextWord.equals(word))
			{
				return true;
			}
		}		
		return false;
	}
	
	/**
	 * Validates the specified array.
	 * @param lineArray The array to validate.
	 * @return
	 */
	private boolean isValidArray(String[] lineArray)
	{
		// Check if the array has a valid size.
		if(lineArray.length != 2)
			return false;
		
		// Check if the second item in the array is an Integer.
		try
		{
			Integer.parseInt(lineArray[1]);
		}
		catch(NumberFormatException e)
		{
			return false;
		}
			
		// Passed all checks.
		return true;
	}
}
